﻿using QuickChat_Service.Repositories.Repositories.Interfaces;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Web;

namespace QuickChat_Service.Repositories.Repositories.Implementations
{
    public class EFRepository<T> : IRepository<T> where T : class
    {
        protected DbContext DbContext { get; set; }
        protected DbSet<T> DbSet { get; set; }

        public EFRepository(DbContext dbContext)
        {
            if (dbContext == null)
            {
                throw new ArgumentNullException("dbContext");
            }

            this.DbContext = dbContext;
            this.DbSet = this.DbContext.Set<T>();
            //this.DbContext.Configuration.ProxyCreationEnabled = false;
            //this.DbContext.Configuration.LazyLoadingEnabled = false;
        }

        public virtual IQueryable<T> GetAll()
        {
            return DbSet;
        }

        public virtual T GetById(int id)
        {
            return DbSet.Find(id);
        }

        public virtual void Add(T entity)
        {
            DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
            if (dbEntityEntry.State != EntityState.Detached)
            {
                dbEntityEntry.State = EntityState.Added;
            }
            else
            {
                DbSet.Add(entity);
            }

            SaveChanges();
        }

        public virtual void Update(T entity, int targetId)
        {
            if(targetId <= 0)
            {
                throw new Exception("Cannot update an item with key of zero or less");
            }

            DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
            if (dbEntityEntry.State == EntityState.Detached)
            {
                DbContext.Entry(DbSet.Find(targetId)).CurrentValues.SetValues(entity);
            }
            //dbEntityEntry.State = EntityState.Modified;
            SaveChanges();
        }

        public virtual void Delete(T entity)
        {
            DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
            if (dbEntityEntry.State != EntityState.Deleted)
            {
                dbEntityEntry.State = EntityState.Deleted;
            }
            else
            {
                DbSet.Attach(entity);
                DbSet.Remove(entity);
            }
            SaveChanges();
        }

        public virtual void Delete(int id)
        {
            var entity = GetById(id);
            if (entity == null)
            {
                return;
            }

            Delete(entity);
            SaveChanges();
        }

        public void SaveChanges()
        {
            DbContext.SaveChanges();
        }
    }
}